# 10 Verilog 1. 关于Verilog HDL语言中输入、输出信号的描述,哪句话是错的() 1. input是输入信号的说明语句,output是输出信号的说明语句 2. input和output不是信号的定义语句 3. input和output说明的信号都可以是多个 4. 调用模块时,只需要给出输入信号,不需要给出输出信号 2. 关于Verilog HDL语言,哪句话是错的() 1. 一个module定义内部,可以再定义一个模块,该模块称为子模块; 2. 一个module调用其他模块时,是模块的实例化,即连接了相应的器件; 3. 一个module描述的就是一个电路的类型; 4. 一个程序可以有多个module,其中一个顶层的module负责整个电路的对外接口。 3. Verilog HDL语言中对线网(wire)型信号定义的说法,哪句话是错的() 1. wire型的信号表示同一条线路上的信号; 2. 一个8位宽wire型的信号定义为wire a\[0:7\]; 3. 一个8位宽wire型的信号定义为wire \[7:0\]a; 4. 一个wire型的信号输入一个非门后,结果还是wire型信号。 4. 以下关于Verilog HDL语言描述错误的是() 1. 每个模块描述的是一个电路类型,可以通过实例化变为多个电路;. 2. 用parameter定义的是符号常量; 3. 模块的实例化就是生成了一个该模块的电路,并与其他电路进行了信号连接。 4. 用begin和end标记是语句块,它的内部不能再有一组begin和end;. 5. 以下关于Verilog HDL语言错误的是() 1. 采用原理图和硬件描述语言都可以进行数字电路设计; 2. 用parameter定义的是符号常量; 3. 模块内部不能重复调用另一个模块多次。 4. 在module内部对电路的各个D信号的描述是并列关系,无先后顺序; 6. 以下关于逻辑综合Synthesis的说法错误的是() 1. 逻辑综合就是验证硬件描述语言HDL的电路设计正确与否的过程;. 2. 逻辑综合可以产生所设计电路模型的门级网表; 3. 逻辑综合结果可以用于制作集成电路或印刷电路板 4. 逻辑综合可以产生所设计数字电路模型的基本电子元件列表; 7. 以下关于逻辑仿真Simulation的说法错误的是() 1. 逻辑仿真是对数字逻辑电路的结构和行为进行预测; 2. 逻辑仿真可以给出输出信号的时序波形图; 3. 逻辑仿真需要连接FPGA芯片,然后在电脑上观察输出波形。 4. 逻辑仿真需要产生出测试电路的信号,将其输入被测试模块,查看结果。 8. 以下关于assign语句的说法错误的是() 1. assign语句用于描述等号右边的变量与等号左边的变量之间的逻辑关系; 2. assign语句相当于等号两边的变量采用相应的门电路进行了物理连接; 3. 多条assign语句是顺序执行的; 4. 多条assign语句的前后顺序可以随意变化,电路不会改变。 9. 以下关于Verilog语言描述错误的是() 1. always下面可以出现多条语句或多个语句块; 2. always语句表示对某个信号的变化敏感; 3. assign语句和always语句是并列关系; 4. HDL是Hardware Description Language的缩写。 10. 以下关于Verilog HDL语言描述错误的是() 1. Verilog HDL语言中每个变量或者常量都有相应的类型; 2. 定义信号或变量时的标识符可以是字母、数字、\$字符和下划线; 3. 标识符可以采用wire或者reg; 4. 可用/...../或//对Verilog程序作注释。 11. 在Verilog HDL中,下列标识符不正确的是()。 1. Real? 2. Count 3. INITIAL 4. \_2to1MUX 12. 非阻塞性赋值运算符为()。 1. \<= 2. = 3. == 4. =\> 13. 在verilog HDL中,下列语句哪个不是循环语句?() 1. while 2. repeat 3. case 4. for 14. 已知a =4'b1010,b=4'b1100,那么&(a&b)=() 1. 1' b0 2. 4'b1000 3. 4' b1010 4. 1' b1 15. 如下Verilog HDL程序所描述的是一个数据选择器,对它的描述错误的是() ```verilog module LL(Y, X, S); input [1:0]X; input S; output reg Y; always @ (S, X) if(S==0) Y <= X[0]; else Y <= X[1]; endmodule ``` 1. 这个L器件是一个组合逻辑电路; 2. 这个器件可根据S的值实现对两路信号的选择; 3. X和S的类型不明确; 4. 该程序里Y必须是reg类型,不能是wire类型。 16. 在语句 `assign Y=sel ? 0:1;` 中,当 `sel=0` 时,`Y`的值为() 1. x 2. 1 3. 0 4. z 17. 在连续赋值语句`assign`中被赋值的变量应该定义为哪种数据类型() 1. reg 2. time 3. wire 4. wire、reg均可 18. 基于EDA技术的现代电子系统设计流程为:原理图/HDL文本输入→功能仿真→()→布局布线→()→编程下载→硬件测试。正确的是()。 ①功能仿真②时序仿真③逻辑综合④配置⑤分配管脚 1. ①⑤ 2. ③② 3. ⑤① 4. ④② 19. 在串行语句块中,阻塞赋值语句按照它们在块中排列的顺序依次执行,即前一条语句没有完成赋值之前,后面的语句不可能被执行。() 20. 关于组合逻辑电路的Verilog HDL编程描述正确的是() 1. 组合逻辑电路的输出只能是 `wire` 类型的; 2. 组合逻辑电路的描述只能采用 `assign` 语句,不能采用 `always` 语句; 3. 组合逻辑电路的描述只能依赖真值表或表达式; 4. 组合逻辑电路可以是多输入信号,也可以是多输出信号。 :::{dropdown} Answer 1. {bdg-primary}`D` 选项D是错误的,调用模块时必须给出所有端口信号的连接,包括输入端和输出端的信号。 2. {bdg-primary}`A` 选项A是错误的,模块定义中只能调用其他模块,不能定义其他模块。 3. {bdg-primary}`B` 选项B是错的,位宽应写在a前面。 4. {bdg-primary}`D` 选项D是错的,begin和end内部是可以继续出现begin和end语句块的。 5. {bdg-primary}`C` 选项C是错的,同一个模块可以被调用多次,生成的是同一种电路,但接口连接可能不同。 6. {bdg-primary}`A` 选项A是错误的,用于验证电路设计的是逻辑仿真,不是逻辑综合。 7. {bdg-primary}`C` 选项C是错误的,逻辑仿真只需要在电脑上进行,不需要连接实际芯片。 8. {bdg-primary}`C` 选项C是错误的,因为多条assign语句是并列关系,都是用于分别描述电路内的信号之间的关系。 9. {bdg-primary}`A` 选项A是错的,因为always下面只能出现一条语句或一个begin和end围起来的语句块。 10. {bdg-primary}`C` 选项C是错误的,因为wire和reg是用于定义的特殊关键字,不能用作标识符。 11. {bdg-primary}`A` 标识符通常由英文字母、数字、\$符和下划线组成,并且规定标识符必须以英文字母或下划线开始,不能以数字或\$符开头。标识符有大、小写之分。C是大写的initial,是可以用作标识符的。 12. {bdg-primary}`A` 阻塞性赋值运算符为=,非阻塞性赋值运算符为\<=。 13. {bdg-primary}`C` 答案为C, case为条件/分支语句。 14. {bdg-primary}`A` 答案为A,令Z=a & b表示对a和b进行位与运算,将a和b的各位对应相与,结果为Z=4’b1000。&(Z) 表示对Z进行缩位与运算,即将Z的所有位相与,结果为1’b0。 15. {bdg-primary}`C` 选项C是错的。程序没有指定类型的信号,默认为wire类型的。 16. {bdg-primary}`B` 在条件运算符cond_expr ? expr1 : expr2中,假如cond_expr为真(即值为1 ),选择expr1;假如cond_expr为假(值为0 ),选择expr2。,因此sel=0时,Y=1。 17. {bdg-primary}`C` 正确选项为C,在关键词assign引导的连续赋值语句中被赋值的变量只能是wire类型。reg和time类型均属于寄存器类型,寄存器类型的变量不能在连续赋值语句中被赋值。 18. {bdg-primary}`B` 略 19. {bdg-success}`True` 对,略 20. {bdg-primary}`D` 选项D是对的,输出信号可以有多个,每个输出信号可以和不同的输入信号存在逻辑关系。AB是错的,组合逻辑电路可以采用assign语句(对wire变量赋值),也可以采用always语句(对reg变量赋值)。 ::: 21. 写一个Verilog HDL程序对两路信号进行选择,每路信号都是一个8位数据。 :::{dropdown} Answer 与第14题的题干类似,把输入信号改为8位宽的即可。 ```verilog module LL(Y, X1, X2, S); input [7:0] X1, X2; input S; output reg [7:0] Y; always @(S, X1, X2) if(S==0) Y <= X1; //可用<= 或 = else Y <= X2; //可用<= 或 = endmodule ``` ::: 22. 编写verilog程序实现一个4线-16线译码器。(满分5分) :::{dropdown} Answer ```verilog module decoder4_16(input A, En, output Y); wire [3:0] A; reg [15:0] Y; integer k; always @ ( * ) if (En==0) Y=16'b1111_1111_1111_1111; else begin Y=16'b1111_1111_1111_1111; for(k=0; k<=15; k=k+1) //不能用k++ if(A==k) Y[k]=0; else Y[k]=1; end endmodule ``` 其中for改为case也可以,就是写起来麻烦点。 ::: 23. 编写verilog程序:输入-个8位无符号二进制数输出其8421BCD码结果。(满分6分) :::{dropdown} Answer 输入8位,输出12位。注意需要用阻塞赋值。答案不唯一 ```verilog module binary2bcd(input x, output y); wire [7:0] x; reg [11:0] y; always @* begin y[9:8] = x/100; y[7:4] = (x-y[9:8]*100)/10; y[3:0] = x-y[9:8]*100-y[7:4]*10; end endmodule ``` ::: 24. 设计3个模块: - 模块1是1位全加器; - 模块2是共阴极七段式显示译码器; - 模块3调用前2个模块,实现对两个2位信号的求和,并在七段式数码管上显示结果。 :::{dropdown} Answer ```verilog module adder(input D1, D2, CI, output reg S, CO); always @(*) {CO, S} = D1 + D2 + CI; endmodule module seg7_decoder(input [3:0] D, output reg [6:0] code); always @(*) case(D) 4'd0: code = 7'b1111110; 4'd1: code = 7'b0110000; // ...其他数字的编码 default: code = 7'b0000000; endcase endmodule module disp(input [1:0] dataA, input [1:0] dataB, output [6:0] disp_code); wire [3:0] S; wire tmp_C; assign S[3] = 0; adder adder_1( .D1(dataA[0]), .D2(dataB[0]), .CI(0), .S(S[0]), .CO(tmp_C) ); adder adder_2( .D1(dataA[1]), .D2(dataB[1]), .CI(tmp_C), .S(S[1]), .CO(S[2]) ); seg7_decoder seg7_decoder_1( .D(S), .code(disp_code) ); endmodule ``` ::: 25. 写一个Verilog HDL程序,对一个8位的、带同步置位复位端的(低电平有效)、上升沿触发的D触发器进行描述。注意输出一个Q即可,不需要Q非。 :::{dropdown} Answer ```verilog module D_FF(input [7:0]D, CP, S, R, output reg [7:0]Q ); always @ ( posedge CP ) if (~S || ~R) if (~S ) Q <= 1'b1; else Q <= 1'b0; else Q <= D ; endmodule ``` ::: 26. 写—个Verilog HDL程序,对一个8位的、带异步置位和复位端的(低电平有效)、下降沿触发的D触发器进行描述。注意:输出一个Q即可,不需要Q非。 :::{dropdown} Answer ```verilog module D_FF(input [7:0]D, CP, Sd, Rd, output reg [7:0]Q ); always @ ( negedge CP, negedge Sd, negedge Rd ) if (~Sd || ~Rd) if (~Sd ) Q <= 1'b1; else Q <= 1'b0; else Q <= D ; endmodule ``` ::: 27. 对这个米利型的状态图编程。 ![image1](../../../resources/eb07abc328c84a22b4e692896d0a85e5.png) :::{dropdown} Answer ```verilog module mm(input CP, Rst, Data, output [1:0] wire Q, output reg Y); parameter S0=2'b00, S1=2'b01, S2=2'b10, S3=2'b11; reg [1:0] state; always @ (posedge CP, negedge Rst) if (~Rst) state <= S0; else case (state) S0: if (Data) state<=S1; S1: if (Data) state<=S2; else state <=S3; S2: if (~Data) state<=S0; S3: if (~Data) state<=S0; else state <=S1; endcase always @ (Data, state) case (state) S0: Y<=0; S1: Y<=0; S2: Y<=0; S3: if (~Data) Y<=0; else Y<=1; endcase assign Q = state; endmodule ``` ```verilog module mm(input CP, Rst, Data, output [1:0] wire Q, output reg Y); parameter S0=2'b00, S1=2'b01, S2=2'b10, S3=2'b11; reg [1:0] current_state, next_state; always @ (posedge CP, negedge Rst) if (~Rst) current_state <= S0; else current_state <= next_state; always @ (Data, current_state) case (current_state) S0: if (Data) next_state<=S1; S1: if (Data) next_state<=S2; else next_state <=S3; S2: if (~Data) next_state<=S0; S3: if (~Data) next_state<=S0; else next_state <=S1; endcase always @ (Data, current_state) case (current_state) S0: Y<=0; S1: Y<=0; S2: Y<=0; S3: if (~Data) Y<=0; else Y<=1; endcase assign Q = current_state; endmodule ``` ::: 28. 对这个穆尔型的状态图编程。 ![image2](../../../resources/280dc2ceebe44fe2b6595f8fd34a39e4.png) :::{dropdown} Answer ```verilog module mm(input CP, Rst, output [1:0] wire Q, output reg Y); parameter a=2'b00, b=2'b01, c=2'b10, d=2'b11; reg [1:0] state; always @ (posedge CP, negedge Rst) if (~Rst) state <= a; else case (state) a: begin state<=b; Y<=0; end b: begin state<=c; Y<=0; end c: begin state<=d; Y<=1; end d: begin state<=a; Y<=0; end endcase assign Q=state; endmodule ``` ```verilog module mm(input CP, Rst, output [1:0] wire Q, output reg Y); parameter a=2'b00, b=2'b01, c=2'b10, d=2'b11; reg [1:0] state; always @ (posedge CP, negedge Rst) if (~Rst) state <= a; else case (state) a: state<=b; b: state<=c; c: state<=d; d: state<=a; endcase always @ (state) case (state) a: Y<=0; b: Y<=0; c: Y<=0; d: Y<=1; endcase assign Q=state; endmodule ``` ::: 29. 以下是某控制电路的状态图,编写Verilog程序。 ![image3](../../../resources/02dbe51aa7bb48a8b9c610a921804a2b.png) :::{dropdown} Answer 米利型的,状态转换和输出要分开写。 ```verilog module mm(input reset, clk, A, output state, F, G); reg [1:0] state; reg F, G; parameter idle=2'b00, start=2'b01, stop=2'b10, clear=2'b11; always @ (posedge clk, negedge reset) if (~reset) begin state<=idle; F<=0; G<=0; end else case (state) idle: if(A) begin state<=start; end start: if(!A) begin state<=stop; end stop: if(A) begin state<=clear; end clear: if(!A) begin state<=idle; end endcase always @ (state, A) case (state) idle: if(A) begin G<=0; end start: stop: if(A) begin F<=1; end clear: if(!A) begin F<=0; G<=1; end endcase endmodule ``` ::: 30. 采用Verilog设计简单的红绿灯。绿灯30s;黄灯5s;红灯35s。已知系统时钟clk= 1MHz。要求: 1. 设计分频模块;计数器模块。 2. 顶层模块引用分频模块和计数模块。 3. 编写仿真文件,并进行仿真。 :::{dropdown} Answer 先给出思路: ![image10](../../../resources/3778df3c18c04a6f9e010c79214f852e.png) 设计一个70进制的秒计数器。各灯在指定的范围内亮即可。秒计数器通过系统时钟分频得到1s的使能信号,再采用通用计数器,实现秒计数器。同学们要注重知识的积累,通用模块我们经常会用。保存的时候,一个文件仅保存一个模块,文件名和模块名相同。 ```verilog // 分频模块 module divider( input clk, input rst_n, output reg clk_1Hz ); parameter DIV_COUNT = 500000; // 1MHz到1Hz需要分频1000000次,这里取一半 reg [19:0] count; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin count <= 0; clk_1Hz <= 0; end else if(count == DIV_COUNT - 1) begin count <= 0; clk_1Hz <= ~clk_1Hz; end else count <= count + 1; end endmodule // 计数器模块 module counter( input clk, input rst_n, input en, output reg [6:0] count ); always @(posedge clk or negedge rst_n) begin if(!rst_n) count <= 0; else if(en) begin if(count == 69) count <= 0; else count <= count + 1; end end endmodule // 顶层模块 module traffic_light( input clk, input rst_n, output reg red, yellow, green ); wire clk_1Hz; wire [6:0] count; divider div( .clk(clk), .rst_n(rst_n), .clk_1Hz(clk_1Hz) ); counter cnt( .clk(clk), .rst_n(rst_n), .en(clk_1Hz), .count(count) ); always @(count) begin // 绿灯30s if(count < 30) begin green = 1; yellow = 0; red = 0; end // 黄灯5s else if(count < 35) begin green = 0; yellow = 1; red = 0; end // 红灯35s else begin green = 0; yellow = 0; red = 1; end end endmodule ``` ::: 31. 编写一个FPGA向SRAM写数据的模块。该模块接收到start信号后,在4个时钟周期内,产生如图所示的Addr、/cs、wr和data信号,其中地址信号addr为8地址线,data是8位数据线,当一个"写"结束后,数据线上输出高阻态。 模块输入:clk时钟信号;rst_n低电平复位信号;start启动写操作的信号;dataIn,8位数据输入; addrIn,8位地址输入; 输出信号:Addr(8)、/cs、/wr、data(8) ![image4](../../../resources/1262820908d540229cb9af89c6ba79c2.png) ![image5](../../../resources/319b989138fa4b94b2579678c5d603be.png) :::{dropdown} Answer ```verilog module WriteToSRAM( input wire clk, input wire rst_n, input wire start, input wire [7:0] dataIn, input wire [7:0] addrIn, output wire cs_n, output wire wr_n, output wire [7:0] data, output reg [7:0] addr ); parameter S0 = 5'b00001; parameter S1 = 5'b00010; parameter S2 = 5'b00100; parameter S3 = 5'b01000; parameter S4 = 5'b10000; reg [4:0] state; always @(posedge clk) begin if(rst_n == 1'b0) state <= S0; else case(state) S0: if(start) begin state <= S1; addr <= addrIn; end S1: state <= S2; S2: state <= S3; S3: state <= S4; S4: state <= S0; default: state <= S0; endcase end assign cs_n = (state == S0) ? 1'b1 : 1'b0; assign wr_n = (state == S2 || state == S3) ? 1'b0 : 1'b1; assign data = (state != S0) ? dataIn : 8'hZZ; endmodule ``` :::